package com.future.bs.component.report;

import cn.hutool.core.collection.CollectionUtil;
import com.future.bs.context.Context;
import com.future.bs.component.business.BusinessPredicate;
import com.future.bs.context.BusinessStatus;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.List;

/**
 * <p>
 * 抽象并行业务执行结果
 * </p>
 *
 * @author Jingjie
 * @since 2020-11-08 18:05
 */
public class ParalleledReport<T extends Context> extends DefaultReport<T> {
    private static final Logger LOGGER = LoggerFactory.getLogger(ParalleledReport.class);

    private final List<Report<T>> reports;

    public ParalleledReport(List<Report<T>> reports) {
        this.reports = reports;
        this.status = this.getStatusFromReports();
        this.error = this.getErrorFromReports();
        this.context = this.getContextFromReports();
    }

    private BusinessStatus getStatusFromReports() {
        if (CollectionUtil.isEmpty(reports)) {
            LOGGER.warn("The business reports is empty. skipping get status.");
            return BusinessStatus.SUCCESS;
        }
        for (Report<T> report : this.reports) {
            if (BusinessPredicate.FAILED.apply(report)) {
                return BusinessStatus.FAILED;
            }
        }
        return BusinessStatus.SUCCESS;
    }

    private Throwable getErrorFromReports() {
        if (CollectionUtil.isEmpty(reports)) {
            LOGGER.warn("The business reports is empty. skipping get error.");
            return null;
        }
        for (Report<T> report : reports) {
            Throwable error = report.getError();
            if (error != null) {
                LOGGER.error("Execute business occur error.", error);
                return error;
            }
        }
        return null;
    }

    private T getContextFromReports() {
        // todo 考虑此处如何更好实现
        if (CollectionUtil.isEmpty(this.reports)) {
            LOGGER.warn("The business reports is empty. skipping get context.");
            return null;
        }
        // 返回第一个context
        Report<T> report = this.reports.stream().filter(re -> re.getContext() != null).findFirst().orElse(null);
        if (report == null) {
            LOGGER.warn("The business report is null. skipping get context.");
            return null;
        }
        return report.getContext();
    }
}
